OpenRoads Designer CONNECT Edition SDK Help

Find intersection between Terrain & Smart line

The below code snippet shows how to find the intersection between 3D line and a terrain surface. The 3D line here is a LineString object. LineString is a set of connected lines.

Example

//Required References
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.SDK;
using Bentley.CifNET.LinearGeometry;


//Element selected from UI of type LineString 
Element el=…; //selected from UI 

if (el.ElementType == MSElementType.LineString)
                    TerrainAndLineIntersection(el);


public void TerrainAndLineIntersection(Element el)
        {
            //Get active connection of dgn model  
            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
            if (sdkCon == null)
                return;

            //Get geometric model
            GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
            if (geomModel == null)
                return;

            SurfaceEntity activeSurface = geomModel.ActiveSurface;


            //Validate terrain surface and selected element
            if (activeSurface != null && activeSurface is TerrainSurface && el.ElementType == MSElementType.LineString)
            {
                TerrainSurface surface = activeSurface as TerrainSurface;
                List<LinearElement> segments = new List<LinearElement>();

                //Get active Dgn model
                DgnModel activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();

                //Get model info to get units 
                ModelInfo info = activeModel.GetModelInfo();

                //Convert Element to LineString 
                Bentley.DgnPlatformNET.Elements.LineStringElement lineString = el as Bentley.DgnPlatformNET.Elements.LineStringElement;
                List<Bentley.GeometryNET.DPoint3d> pointList = new List<Bentley.GeometryNET.DPoint3d>();
                Bentley.GeometryNET.CurvePrimitive curvePrim = lineString.GetCurveVector().GetPrimitive(0);
                curvePrim.TryGetLineString(pointList);

                //Get LineString points 
                for (int i = 0; i < pointList.Count - 1; i++)
                {
                    Bentley.GeometryNET.DPoint3d point1 = pointList[i];
                    Bentley.GeometryNET.DPoint3d point2 = pointList[i + 1];
                    //Convert units to meter
                    point1.Set(point1.X / info.UorPerMeter, point1.Y / info.UorPerMeter, point1.Z / info.UorPerMeter);
                    point2.Set(point2.X / info.UorPerMeter, point2.Y / info.UorPerMeter, point2.Z / info.UorPerMeter);
                    //Create linear elements after converting units  
                    segments.Add(new Line3d(point1, point2));
                }

                //For each linear element find intersection of it with terrain 
                foreach (LinearElement le in segments)
                {
                    //Get intersecting line here
                    Bentley.GeometryNET.DSegment3d intersectLine = new Bentley.GeometryNET.DSegment3d();

                    //Call IntersectVector()
                    bool intersects = IntersectVector(surface.DTM, out intersectLine, le.StartPoint.Coordinates, le.EndPoint.Coordinates);

                }
            }
        }

public bool IntersectVector(Bentley.TerrainModelNET.DTM dtm, out Bentley.GeometryNET.DSegment3d intersectionSegment, Bentley.GeometryNET.DPoint3d startPt, Bentley.GeometryNET.DPoint3d endPt)
        {
            intersectionSegment = new Bentley.GeometryNET.DSegment3d();
            //Project the start and end points of line to terrain surface
            var drapeResult = dtm.DrapeLinearPoints(new Bentley.GeometryNET.DPoint3d[] { startPt, endPt });
            double vectorDist = startPt.DistanceXY(endPt);
            double vectorZDiff = endPt.Z - startPt.Z;
            bool hasPrevPt = false;
            Bentley.GeometryNET.DPoint3d prevPt = new Bentley.GeometryNET.DPoint3d();
            double prevZ = 0;
            bool prevAbove = false;
            foreach (var drapePt in drapeResult)
            {
                //Check Drapped point position i.e. inside terrain or outside terrain boundry
                if (drapePt.Code == Bentley.TerrainModelNET.DTMDrapedLinearElementPointCode.External || drapePt.Code == Bentley.TerrainModelNET.DTMDrapedLinearElementPointCode.Void)
                {
                    hasPrevPt = false;
                    continue;
                }

                Bentley.GeometryNET.DPoint3d newPt = drapePt.Coordinates;
                double newZ = startPt.Z + (drapePt.DistanceAlong / vectorDist) * vectorZDiff;
                bool newAbove = newZ > newPt.Z;
                if (hasPrevPt)
                {
                    if (newAbove != prevAbove)
                    {
                        //Create line segment from start point and end point of line
                        Bentley.GeometryNET.DSegment3d seg1 = new Bentley.GeometryNET.DSegment3d(startPt, endPt);
                        //Create line from drapped points from start point and end point on terrain
                        Bentley.GeometryNET.DSegment3d seg2 = new Bentley.GeometryNET.DSegment3d(prevPt, newPt);

                        double f1, f2;
                        //intersect both line segment and terrain segment
                        Bentley.GeometryNET.DSegment3d.ClosestApproachSegment(seg1, seg2, out intersectionSegment, out f1, out f2);

                        //Get intersection point from intersection line 
                        Bentley.GeometryNET.DPoint3d intersectPt = intersectionSegment.StartPoint;
                        return true;
                    }
                }

                hasPrevPt = true;
                prevPt = drapePt.Coordinates;
                prevZ = newZ;
                prevAbove = newAbove;
            }
            return false;
        }

In the above code, Element el represents the LineString selected from the UI.